package com.oneinlet

import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageDecoder
import io.netty.handler.codec.LengthFieldBasedFrameDecoder
import io.netty.handler.codec.MessageToMessageDecoder
import io.netty.util.ReferenceCountUtil
import org.slf4j.LoggerFactory

/**
 * Created by WangZiHe on 2019/1/7/007
 * QQ/WeChat:648830605
 * QQ-Group:368512253
 * Blog:www.520code.net
 * Github:https://github.com/yancheng199287
 */

class YCMessageDecoder(maxFrameLength: Int = Pandora.MAX_FRAME_LENGTH,
                       lengthFieldOffset: Int = Pandora.LENGTH_FIELD_OFFSET,
                       lengthFieldLength: Int = Pandora.LENGTH_FIELD_LENGTH,
                       lengthAdjustment: Int = Pandora.LENGTH_ADJUSTMENT,
                       initialBytesToStrip: Int = Pandora.INITIAL_BYTES_TO_STRIP) : LengthFieldBasedFrameDecoder(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip) {

    private val logger = LoggerFactory.getLogger("YCMessageDecoder")

    override fun decode(ctx: ChannelHandlerContext?, byteBuf1: ByteBuf?): Any? {
        logger.debug("开始解码， 当前承载的byteBuf1： $byteBuf1  ")

        val byteBufObject = super.decode(ctx, byteBuf1) ?: return null
        ReferenceCountUtil.release(byteBuf1);
        val byteBuf = byteBufObject as ByteBuf

        val readableLength = byteBuf.readableBytes()
        logger.debug("开始解码，byteBuf 不为null readableLength: $readableLength, Pandora.HEADER_LENGTH:${Pandora.HEADER_LENGTH}")

        // 如果当前可读取的字节数小于最基本的头部长度，那么就是不完整的一个包
        if (readableLength < Pandora.HEADER_LENGTH) {
            return null
        }

        // 读取数据包的头部长度值，注意每次读取某个单位的字节长度，指针会偏移
        val frameLength = byteBuf.readInt()
        //readableBytes 是可读的总字节数   如果可读的字节数小于我们编码的时候需求的最大字节数，那么是不完全的一个数据包
        if (readableLength < frameLength) {
            return null
        }

        val pandora = Pandora()

        // 读取内容长度
        val contentLength = byteBuf.readInt()
        // 判断是否存在内容长度，如果存在则读取指定长度的字符串内容
        if (contentLength > 0) {
            pandora.content = byteBuf.readCharSequence(contentLength, Pandora.CHARSET).toString()
        }

        // 读取本次消息类型
        pandora.msgType = byteBuf.readByte()
        // 读取 通道ID
        pandora.channelId = byteBuf.readCharSequence(Pandora.CHANNEL_ID_LENGTH, Pandora.CHARSET).toString()

        // 完整的数据包长度 - 减去头部长度（记录长度的大小+包含消息类型长度的大小+记录内容长度的大小+通道ID的大小） -减去内容长度的大小 = 等于 最后的承载外部APP数据的大小
        val data = ByteArray(frameLength - Pandora.HEADER_LENGTH - contentLength)
        byteBuf.readBytes(data)
        pandora.data = data
        logger.debug("解码完成， 当前获取的对象pandora： $pandora")
        return pandora
    }


}